#include "StdAfx.h"
#include "Command.h"
#include <Shlwapi.h>
#include <ShlObj.h>

#include "CommandsRegistry.h"
#include "NetworkUtils.h"
#include "PathUtils.h"

#include <vector>

class CopyFullPath : public ICommand
{
public:
    tchar_string GetMenuItem() const { return _T("File Path"); }
    tchar_string GetDescription() const { return _T("Copy the full file path(s) to the clipboard"); }
    tchar_string GetContent(tchar_string const& fullPath) const { return fullPath; }
};

class CopyFileName : public ICommand
{
    tchar_string GetMenuItem() const { return _T("File Name"); }
    tchar_string GetDescription() const { return _T("Copy the file name(s) to the clipboard"); }
    tchar_string GetContent(tchar_string const& fullPath) const { return PathFindFileName(fullPath.c_str()); }
};

class CopyShortPath : public ICommand
{
    tchar_string GetMenuItem() const {return _T("Short Path"); }
    tchar_string GetDescription() const { return _T("Copy full file path(s) to the clipboard using short names"); }
    tchar_string GetContent(tchar_string const& fullPath) const { return PathUtils::shorten(fullPath); }
};

class CopyUNCPath : public ICommand
{
    tchar_string GetMenuItem() const { return _T("UNC Path"); }
    tchar_string GetDescription() const { return _T("Copy full UNC file path(s) to the clipboard"); }
    tchar_string GetContent(tchar_string const& fullPath) const
    {
        using namespace NetworkUtils;

        if (PathIsUNC(fullPath.c_str())) 
        {
            return fullPath;
        }

        // now we know that the path looks like X:\....
        tchar_string drive(fullPath.substr(0,2));

        // if that's a mapped drive, get unc connection string and concat to the relative path
        tchar_string connection = getDriveConnection(drive);
        if (!connection.empty())
        {
            return connection += fullPath.substr(2);
        }

        // otherwise, if the path in under a shared path, use that
        SharesList shares = getShares();
        for (SharesList::const_iterator pShare = shares.begin(), end = shares.end(); pShare != end; ++pShare)
        {
            tchar_string shareName = pShare->first;
            tchar_string sharedPath = pShare->second;
            if (fullPath.find(sharedPath) == 0)
            {
                tchar_string components[] = {
                    getComputerName(),
                    shareName,
                    fullPath.substr(sharedPath.length() + 1)
                };
                return _T("\\") + PathUtils::pathCombine(components, components + ARRAYSIZE(components));
            }
        }

        return fullPath;
    }
};

class CopyFolder : public ICommand
{
public:
    tchar_string GetMenuItem() const { return _T("Folder Path"); }
    tchar_string GetDescription() const { return _T("Copy folder path(s) to the clipboard"); }

    tchar_string GetContent(tchar_string const& fullPath ) const { return PathUtils::removeFileSpec(fullPath); }
};

class CopyShortFolder : public ICommand
{
public:
    tchar_string GetMenuItem() const { return _T("Folder Short Path"); }
    tchar_string GetDescription() const { return _T("Copy folder short path(s) to the clipboard"); }

    tchar_string GetContent(tchar_string const& fullPath ) const { return PathUtils::shorten(PathUtils::removeFileSpec(fullPath)); }
};

namespace 
{
    bool registerCommands()
    {
       CommandRegistry::instance().registerCommand(new CopyFullPath()) ;
       CommandRegistry::instance().registerCommand(new CopyFileName()) ;
       CommandRegistry::instance().registerCommand(new CopyShortPath()) ;
       CommandRegistry::instance().registerCommand(new CopyUNCPath()) ;
       CommandRegistry::instance().registerCommand(new CopyFolder()) ;
       CommandRegistry::instance().registerCommand(new CopyShortFolder()) ;

       return true;
    }

    bool registered = registerCommands();
}